package com.zues.thread.design_mode.alternating_execute;

import lombok.extern.slf4j.Slf4j;

import java.util.concurrent.locks.LockSupport;

/**
 * 使用park、unpark 演示交替执行Demo
 * 期望效果：三个线程，轮流打印a、b、c，打印5次
 * 线程1：a
 * 线程2：b
 * 线程3：c
 * 打印效果 ：abcabcabcabcabc
 */
@Slf4j(topic = "c.Demo3")
public class Demo3 {

    static Thread t1;
    static Thread t2;
    static Thread t3;

    /**
     * 主函数创建三个线程实现交替打印abc
     * @param args 命令行参数（未使用）
     */
    public static void main(String[] args) {
        ParkUnPark park = new ParkUnPark(5);

        // 创建三个线程形成环形唤醒链：
        // t1打印a后唤醒t2 -> t2打印b后唤醒t3 -> t3打印c后唤醒t1
        t1 = new Thread(() -> {
            park.print("a",t2);
        });

        t2 = new Thread(() -> {
            park.print("b",t3);
        });

        t3 = new Thread(() -> {
            park.print("c",t1);
        });

        t1.start();
        t2.start();
        t3.start();

        LockSupport.unpark(t1);
    }

}

/**
 * ParkUnPark类实现基于LockSupport的多线程顺序打印控制
 * 通过park/unpark机制实现线程间的精确唤醒控制
 */
class ParkUnPark{

    private int loopNumber;

    /**
     * 构造函数初始化循环次数
     * @param loopNumber 每个字符需要打印的总次数
     */
    public ParkUnPark(int loopNumber){
        this.loopNumber = loopNumber;
    }

    /**
     * 打印指定字符并唤醒下一个线程
     * @param str 需要打印的字符
     * @param next 下一个需要唤醒的线程对象
     */
    public void print(String str,Thread next){
        for (int i = 0; i < loopNumber; i++) {
            LockSupport.park();
            System.out.print(str);
            LockSupport.unpark(next);
        }

    }

}
